(SST) ShlWAPI.pas Version 1.08

Developer Reference
(SST)ShlWAPI SHUnicodeToUnicode Function
Copies the characters of a Unicode string into the provided buffer.
Scope
Global (i.e. this function can be called/accessed from code in any unit that includes/uses (SST)ShlWAPI.pas).
Syntax
function SHUnicodeToUnicode(pwzSrc : LPCWSTR; pwszDst : LPWSTR; cwchBuf : Integer) : Integer;
Parameters
pwzSrc [in] The address of, or a pointer to, the zero-terminated, Unicode string to copy.
pwszDst [out] The address of, or a pointer to, the null-terminated buffer, into which the function should write the Unicode copy of the input string.
cwchBuf [in] Size, in number Unicode characters, of the buffer specified in parameter pwszDst.
Return Values
If the function succeeds, it returns the number of characters (including the terminating DBCS character) it wrote into the the buffer specified in pwszDst. If the function fails for any reason, it returns zero (0).
Remarks
If the function copies the source string into the provided buffer, it terminates the copied string with a single, Unicode (i.e. two byte) character. If the buffer is larger than necessary, the remainder of the buffer remains unchanged.
In marked contrast to the SHAnsiToAnsi, SHAnsiToUnicode, and SHUnicodeToAnsi functions, if SHUnicodeToUnicode fails due to an undersized output buffer (pwszDst), the function does not copy any portion of the source string into the available buffer, and therefore does not return the number of copied characters (including the terminating, Unicode null-character). Nor, does calling the Windows API function GetLastError() subsequently, return a meaningful error-code.
Unlike many other Windows, API functions, SHUnicodeToUnicode does not return the required buffer size if zero (0) is specified in the cwchBuf parameter, nor if an invalid (e.g. NIL) pointer is passed to the function in pwszDst.
In the documentation accompanying MS SDK 6.1, Microsoft stresses, that calling the function with an insufficiently sized output buffer can compromise application security thru buffer overruns. The function should therefore not be called with an output bffer that cannot store the entire, converted string, including the terminating Unicode null-character. Specifying overlapping in- and output buffers (i.e. buffers that share the same memory range) should also be avoided.
The function is exported by name as of ShlWAPI.dll version 6.0 under Vista, but according to the declaration and documentation in MS SDK version 6.1, it is available as of ShlWAPI.dll 5.0, under Windows 2000. Unfortunately, an ordinal by which function can be accessed in versions pre-dating Vista was not documented. Nonetheless, we were able to determine that the function is exported by ordinal 346 down to and including Windows NT 4.0 with Internet Explorer 5.0 and 98 SE with Internet Explorer 5.0.
Example
PROCEDURE TForm4.TestShlWAPISHUnicodeToUnicode(Sender : TObject); //Support for function as ordinal 346 under Win 98 SE (with IE 5.0) confirmed !!! //Support for function as ordinal 346 under NT 4.0 with IE 5.0 confirmed !!! VAR srcwcharbuf : WideString; VAR srcstrlen : INTEGER; VAR destwcharbuf : ARRAY[0..64] OF WideChar; VAR destbufsize : INTEGER; VAR apiretval : INTEGER; VAR errorcode : INTEGER; VAR newinfoline : STRING; BEGIN srcwcharbuf := ''; FillChar(destwcharbuf, SizeOf(destwcharbuf), #0); destbufsize := 0; apiretval := 0; newinfoline := ''; srcwcharbuf := 'Hello copy Unicode to Unicode World !'; srcstrlen := Length(srcwcharbuf); destbufsize := Length(destwcharbuf); //Initialize dest buffer with text that ought to be replaced by //the SHUnicodeToUnicode function call. Necessary to test //if the function terminates the copied Unicode string with a null character. //The line also exemplifies how useful the SHAnsiToUnicode function can be. SHAnsiToUnicode('A text with which the output buffer was previously initialized', destwcharbuf, destbufsize); newinfoline := 'SHUnicodeToUnicode called with source string "' + srcwcharbuf + '" returned '; apiretval := SHUnicodeToUnicode(PWChar(srcwcharbuf), destwcharbuf, destbufsize); IF apiretval > 0 THEN newinfoline := newinfoline + IntToStr(apiretval) + ' dest buffer : "' + destwcharbuf + '"' ELSE newinfoline := newinfoline + IntToStr(apiretval) + ' (the function call FAILED !)'; Memo1.Lines.Add(newinfoline); //Dest buffer length parameter set to 23 (too short by 10 character) FillChar(destwcharbuf, SizeOf(destwcharbuf), #0); destbufsize := 27; apiretval := 0; newinfoline := ''; errorcode := 0; newinfoline := 'SHUnicodeToUnicode called with source string "' + srcwcharbuf + '" (length: ' + IntToStr(srcstrlen) + ') returned : '; SetLastError(NO_ERROR); apiretval := SHUnicodeToUnicode(PWChar(srcwcharbuf), destwcharbuf, destbufsize); IF apiretval > 0 THEN BEGIN errorcode := INTEGER(GetLastError()); newinfoline := newinfoline + IntToStr(apiretval) + ' and in the dest buffer : "' + destwcharbuf + '"'; Memo1.Lines.Add(newinfoline); newinfoline := 'and GetLastError returned : ' + IntToStr(errorcode); END ELSE BEGIN errorcode := INTEGER(GetLastError()); newinfoline := newinfoline + IntToStr(apiretval) + ' (the function call FAILED !), GetLastError returned : ' + IntToStr(errorcode); END; Memo1.Lines.Add(newinfoline); //Dest buffer length parameter set to 1 (too short by 36 characters) //FillChar(destansibuf, SizeOf(destansibuf), #0); FillChar(destwcharbuf, SizeOf(destwcharbuf), #0); destbufsize := 1; apiretval := 0; newinfoline := ''; errorcode := 0; newinfoline := 'SHUnicodeToUnicode called with source string "' + srcwcharbuf + '" (length: ' + IntToStr(srcstrlen) + ') returned : '; SetLastError(NO_ERROR); apiretval := SHUnicodeToUnicode(PWChar(srcwcharbuf), destwcharbuf, destbufsize); IF apiretval > 0 THEN BEGIN errorcode := INTEGER(GetLastError()); newinfoline := newinfoline + IntToStr(apiretval) + ' and in the dest buffer : "' + destwcharbuf + '"'; Memo1.Lines.Add(newinfoline); newinfoline := 'and GetLastError returned : ' + IntToStr(errorcode); END ELSE BEGIN errorcode := INTEGER(GetLastError()); newinfoline := newinfoline + IntToStr(apiretval) + ' (the function call FAILED !), GetLastError returned : ' + IntToStr(errorcode); END; Memo1.Lines.Add(newinfoline); //Dest buffer length parameter set to 0 FillChar(destwcharbuf, SizeOf(destwcharbuf), #0); destbufsize := 0; apiretval := 0; newinfoline := ''; errorcode := 0; newinfoline := 'SHUnicodeToUnicode called with source string "' + srcwcharbuf + '" (length: ' + IntToStr(srcstrlen) + ') returned : '; SetLastError(NO_ERROR); apiretval := SHUnicodeToUnicode(PWChar(srcwcharbuf), destwcharbuf, destbufsize); IF apiretval > 0 THEN BEGIN errorcode := INTEGER(GetLastError()); newinfoline := newinfoline + IntToStr(apiretval) + ' and in the dest buffer : "' + destwcharbuf + '"'; Memo1.Lines.Add(newinfoline); newinfoline := 'and GetLastError returned : ' + IntToStr(errorcode); END ELSE BEGIN errorcode := INTEGER(GetLastError()); newinfoline := newinfoline + IntToStr(apiretval) + ' (the function call FAILED !), GetLastError returned : ' + IntToStr(errorcode); END; Memo1.Lines.Add(newinfoline); //No dest buffer (pointer param set to NIL) //and buffer length parameter set to 0 FillChar(destwcharbuf, SizeOf(destwcharbuf), #0); destbufsize := 0; apiretval := 0; newinfoline := ''; errorcode := 0; newinfoline := 'SHUnicodeToUnicode called with source string "' + srcwcharbuf + '" (length: ' + IntToStr(srcstrlen) + ') returned : '; SetLastError(NO_ERROR); apiretval := SHUnicodeToUnicode(PWChar(srcwcharbuf), NIL, 0); IF apiretval > 0 THEN BEGIN errorcode := INTEGER(GetLastError()); newinfoline := newinfoline + IntToStr(apiretval) + ' and in the dest buffer : "' + destwcharbuf + '"'; Memo1.Lines.Add(newinfoline); newinfoline := 'and GetLastError returned : ' + IntToStr(errorcode); END ELSE BEGIN errorcode := INTEGER(GetLastError()); newinfoline := newinfoline + IntToStr(apiretval) + ' (the function call FAILED !), GetLastError returned : ' + IntToStr(errorcode); END; Memo1.Lines.Add(newinfoline); Memo1.Lines.Add(''); END;
When run under Windows Vista with SP 1 and IE 8, the above code produces the following results (note the error codes reurned by the Windows API function GetLastError when the function fails):
SHUnicodeToUnicode called with source string "Hello copy Unicode to Unicode World !" returned 38 dest buffer : "Hello copy Unicode to Unicode World !" SHUnicodeToUnicode called with source string "Hello copy Unicode to Unicode World !" (length: 37) returned : 0 (the function call FAILED !), GetLastError returned : 0 SHUnicodeToUnicode called with source string "Hello copy Unicode to Unicode World !" (length: 37) returned : 0 (the function call FAILED !), GetLastError returned : 0 SHUnicodeToUnicode called with source string "Hello copy Unicode to Unicode World !" (length: 37) returned : 0 (the function call FAILED !), GetLastError returned : 0 SHUnicodeToUnicode called with source string "Hello copy Unicode to Unicode World !" (length: 37) returned : 0 (the function call FAILED !), GetLastError returned : 0
Requirements
Unit: Declared and imported in (SST)ShlWAPI.pas
Library: (SST)ShlWAPI.dcu/(SST)ShlWAPI.obj
Unicode: Not applicable.
Min. ShlWAPI.dll version according to MS SDK doc.: 5.0
Min. ShlWAPI.dll version based on SST research: 5.0
Min. OS version(s) according to Microsoft SDK doc.: Windows 2000, Windows 2000 Server, Windows Server 2003, Windows XP
Min. OS version(s) according to SST research.: Windows NT 4.0 with IE 5, Windows 98 SE with IE 5, Windows 2000, Windows XP, Windows Server 2003.
See Also
SHAnsiToAnsi, SHAnsiToUnicode, SHUnicodeToAnsi, StrDup.
 
Windows APIs: SHUnicodeToUnicode SHAnsiToAnsi, SHAnsiToUnicode, SHUnicodeToAnsi, StrDup.


Document/Contents version 1.01
Page/URI last updated on 07.12.2023
 
Copyright © Stoelzel Software Technologie (SST) 2010 - 2022
Suggestions and comments mail to:
webmaster@stoelzelsoftwaretech.com